using System.Collections.Generic;
using UnityEngine;

namespace GameToolkit
{
    [CreateAssetMenu(fileName = "VibrateCurve", menuName = "角色控制/手柄震动曲线")]
    public class InputVibrateCurve : ScriptableObject
    {
        [SerializeField, Tooltip("振幅曲线")]
        AnimationCurve m_PeekByStrength;

        [SerializeField, Tooltip("频率曲线")]
        AnimationCurve m_FrequencyByStrength;

        public float EvaluateVibrate(float strength, float time)
        {
            float peek, freq;
            if (m_PeekByStrength.IsValid())
                peek = m_PeekByStrength.Evaluate(strength);
            else
                peek = strength;
            if (m_FrequencyByStrength.IsValid())
                freq = m_FrequencyByStrength.Evaluate(strength) * 100;
            else
                freq = 100;

            freq = Mathf.Repeat(freq * time + 0.8f, 1);
            freq = Mathf.Clamp01((freq - 0.5f) * 2);

            //var tick = Mathf.CeilToInt(freq * time);
            //if(tick > ticks)
            //{
            //    ticks = tick;
            //    freq = 1;
            //}
            //else
            //{
            //    ticks = tick;
            //    freq = 0;
            //}
            return peek * freq * freq;

        }

    }

    struct VibrateParameter
    {
        public int id;
        public float strength;
        public float untilTime;
    }

    public class EaseInputVibrate
    {

        float mTime;
        List<VibrateParameter> mVibrateArgs;

        public EaseInputVibrate()
        {
            mVibrateArgs = new List<VibrateParameter>(5);
        }

        public void AddVibrate(int id, float strength, float duration)
        {
            var until = mTime + duration;
            VibrateParameter vib;
            vib.id = id;
            vib.strength = strength;
            vib.untilTime = until;
            mVibrateArgs.Add(vib);
            for (int i = mVibrateArgs.Count - 2; i >= 0; i--)
            {
                var v = mVibrateArgs[i];
                if (v.untilTime <= vib.untilTime)
                    mVibrateArgs.RemoveAt(i);
            }
        }

        public void Append(int id, float duration)
        {
            for (int i = mVibrateArgs.Count - 1; i >= 0; i--)
            {
                var vib = mVibrateArgs[i];
                if (vib.id == id)
                {
                    vib.untilTime = mTime + duration;
                    mVibrateArgs[i] = vib;
                    for (int k = i - 1; k >= 0; k--)
                    {
                        var v = mVibrateArgs[k];
                        if (v.untilTime <= vib.untilTime)
                        {
                            mVibrateArgs.RemoveAt(k);
                        }
                    }
                    return;
                }
            }
        }

        public void Stop(int id)
        {
            for (int i = mVibrateArgs.Count - 1; i >= 0; i--)
            {
                var vib = mVibrateArgs[i];
                if (vib.id == id)
                {
                    mVibrateArgs.RemoveAt(i);
                    return;
                }
            }
        }

        public float Evaluate(InputVibrateCurve curve, float deltaTime)
        {
            if (mVibrateArgs.Count == 0)
                return 0;
            mTime += deltaTime;
            var vib = mVibrateArgs[mVibrateArgs.Count - 1];
            var f = vib.strength;
            if (curve != null)
                f = curve.EvaluateVibrate(f, mTime);
            for (int i = mVibrateArgs.Count - 1; i >= 0; i--)
            {
                vib = mVibrateArgs[i];
                if (vib.untilTime <= mTime)
                {
                    mVibrateArgs.RemoveAt(i);
                }
                else
                {
                    break;
                }
            }
            if (mVibrateArgs.Count == 0)
            {
                mTime = 0;
            }
            return f;
        }
    }
}